package com.mengniu.commerce.sync.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mengniu.commerce.common.core.domain.R;
import com.mengniu.commerce.common.core.enums.ModuleEnum;
import com.mengniu.commerce.common.core.enums.PushStatus;
import com.mengniu.commerce.common.core.utils.IdGeneratorSnowflake;
import com.mengniu.commerce.common.core.utils.bean.BeanUtils;
import com.mengniu.commerce.common.template.enums.APIUrlEnum;
import com.mengniu.commerce.sync.api.base.MnResult;
import com.mengniu.commerce.sync.api.base.RefundOrderResult;
import com.mengniu.commerce.sync.api.domain.CreateRefundOrderModel;
import com.mengniu.commerce.sync.api.domain.ExtModel;
import com.mengniu.commerce.sync.api.domain.UpdateRefundOrderModel;
import com.mengniu.commerce.sync.api.dto.RetryDTO;
import com.mengniu.commerce.sync.common.utils.MnResultUtil;
import com.mengniu.commerce.sync.common.utils.RestTemplateUtil;
import com.mengniu.commerce.sync.exception.RetryException;
import com.mengniu.commerce.sync.mapper.RefundOrderMapper;
import com.mengniu.commerce.sync.model.RefundOrderModel;
import com.mengniu.commerce.sync.service.RefundOrderService;
import com.mengniu.commerce.sync.utils.RetryUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.RetryContext;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.retry.support.RetrySynchronizationManager;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * F-C消费者售后订单实现类
 */
@Service
@Slf4j
public class RefundOrderImpl implements RefundOrderService {

    public static final String baseURL = "https://t-openapi-gateway.mengniu.cn/";
    @Resource
    private RestTemplateUtil restTemplateUtil;
    @Resource
    private RefundOrderMapper refundOrderMapper;

    @Resource
    private RetryUtils retryUtils;

    /**
     * F-C消费者售后订单创建API-原子
     */
    @Override
    @Retryable(value = { RetryException.class }, maxAttempts = 8, backoff = @Backoff(delay = 10000))
    public R createRefundOrder(List<CreateRefundOrderModel> createRefundOrderModelList, RetryDTO retryDTO) {
        log.info("F-C消费者售后订单创建API-原子入参{}", JSONObject.toJSONString(createRefundOrderModelList));
        JSONObject param = (JSONObject) JSON.toJSON(createRefundOrderModelList);
        log.info("F-C消费者售后订单创建API-原子入参json参数为{}",JSONObject.toJSONString(param));
        RetryContext context = RetrySynchronizationManager.getContext();
        log.info("F-C消费者售后订单创建API-原子重试次数{}",JSONObject.toJSONString(context));
        JSONObject result = new JSONObject();
        try{
            result = restTemplateUtil.doPost(param, baseURL + APIUrlEnum.REFUND_ORDER_CREATE.getPath());
        }catch (Exception e){
            log.error("调用F-C消费者售后订单创建接口失败",e);
            Long id = retryUtils.insertOrUpdate(param, retryDTO.getSource(), retryDTO.getStoreName(), ModuleEnum.REFUND_ORDER.getModuleName(), APIUrlEnum.REFUND_ORDER_CREATE.getMethod(), context.getRetryCount(), e.getMessage(),retryDTO.getRetryId());
            retryDTO.setRetryId(id);
            throw new RetryException("发生了重试异常{}", e);
        }
        RefundOrderResult refundOrderResult = JSONObject.parseObject(result.toJSONString(), RefundOrderResult.class);
        log.info("调用F-C消费者售后订单创建接口响应转换为refundOrderResult{}",JSONObject.toJSONString(refundOrderResult));
        if (Objects.isNull(refundOrderResult) || ! refundOrderResult.getSuccess()){
            return R.fail(result,refundOrderResult.getMsg());
        }
        this.insertRefundOrderModel(createRefundOrderModelList,refundOrderResult);
        return R.ok(refundOrderResult);
    }



    /**
     *F-C消费者售后订单修改API-原子
     */
    @Override
    @Retryable(value = { RetryException.class }, maxAttempts = 8, backoff = @Backoff(delay = 10000))
    public R  updateRefundOrder(List<UpdateRefundOrderModel> createRefundOrderModelList, RetryDTO retryDTO) {
        log.info("F-C消费者售后订单修改API-原子入参{}", JSONObject.toJSONString(createRefundOrderModelList));
        JSONObject param = (JSONObject) JSON.toJSON(createRefundOrderModelList);
        log.info("F-C消费者售后订单修改API-原子入参json参数为{}",JSONObject.toJSONString(param));
        RetryContext context = RetrySynchronizationManager.getContext();
        log.info("F-C消费者售后订单修改API-原子重试次数{}",JSONObject.toJSONString(context));
        JSONObject result = new JSONObject();
        try{
            result = restTemplateUtil.doPost(param, baseURL + APIUrlEnum.REFUND_ORDER_UPDATE.getPath());
        }catch (Exception e){
            log.error("调用F-C消费者售后订单修改接口失败",e);
            Long id = retryUtils.insertOrUpdate(param, retryDTO.getSource(), retryDTO.getStoreName(), ModuleEnum.REFUND_ORDER.getModuleName(), APIUrlEnum.REFUND_ORDER_UPDATE.getMethod(), context.getRetryCount(), e.getMessage(),retryDTO.getRetryId());
            retryDTO.setRetryId(id);
            throw new RetryException("发生了重试异常{}", e);
        }
        RefundOrderResult refundOrderResult = JSONObject.parseObject(result.toJSONString(), RefundOrderResult.class);
        log.info("调用F-C消费者售后订单修改接口响应转换为refundOrderResult{}",JSONObject.toJSONString(refundOrderResult));
        if (Objects.isNull(refundOrderResult) || ! refundOrderResult.getSuccess()){
            return  R.fail(result,refundOrderResult.getMsg());
        }
        this.updateRefundOrderModel(createRefundOrderModelList,refundOrderResult);
        return R.ok(refundOrderResult);
    }

    public void updateRefundOrderModel(List<UpdateRefundOrderModel> createRefundOrderModelList, RefundOrderResult refundOrderResult) {
        RefundOrderResult.ResultData orderResultData = refundOrderResult.getData();
        List<RefundOrderResult.DataModel> errorData = orderResultData.getErrorData();
        List<RefundOrderResult.DataModel> successData = orderResultData.getSuccessData();
        errorData.forEach(dataModel -> {
            createRefundOrderModelList.stream().filter(createRefundOrderModel -> createRefundOrderModel.getSalesOrderNo().equals(dataModel.getSalesOrderNo()))
                    .findFirst()
                    .ifPresent(o -> {
                        RefundOrderModel refundOrderModel = this.modifyRefundOrderModel(o, PushStatus.UPDATE_ERROR.getStatus());
                        refundOrderMapper.updateRefundOrderModel(refundOrderModel);
                    });
        });
        successData.forEach(dataModel -> {
            createRefundOrderModelList.stream().filter(createRefundOrderModel -> createRefundOrderModel.getSalesOrderNo().equals(dataModel.getSalesOrderNo()))
                    .findFirst()
                    .ifPresent(o -> {
                        RefundOrderModel refundOrderModel = this.modifyRefundOrderModel(o, PushStatus.UPDATE_SUCCESS.getStatus());
                        refundOrderMapper.updateRefundOrderModel(refundOrderModel);
                    });
        });
    }

    public RefundOrderModel modifyRefundOrderModel(UpdateRefundOrderModel o, Integer status) {
        String salesOrderNo = o.getSalesOrderNo();
        RefundOrderModel refundOrderModel = refundOrderMapper.selectBySalesOrderNo(salesOrderNo);
        log.info("通过salesOrderNo查询RefundOrderModel数据为{}",JSONObject.toJSONString(refundOrderModel));
        BeanUtils.copyProperties(refundOrderModel,o);
        ExtModel extModel = new ExtModel(o.getExt1(),o.getExt2(),o.getExt3(),o.getExt4(),o.getExt5(),o.getExt6(),o.getExt7(),o.getExt8(),o.getExt9(),o.getExt10());
        refundOrderModel.setExt(extractFieldsAsList(extModel) + "");
        refundOrderModel.setUpdateTime(new Date());
        refundOrderModel.setPushStatus(status);
        List<CreateRefundOrderModel.RefundOrderItemRequest> refundOrderItemRequests = JSONObject.parseArray(refundOrderModel.getRefundOrderItemRequestInfo(), CreateRefundOrderModel.RefundOrderItemRequest.class);
        List<UpdateRefundOrderModel.RefundOrderItemRequest> refundOrderItemRequestList = o.getRefundOrderItemRequestList();
        refundOrderItemRequests.forEach(refundOrderItemRequest -> {
            List<UpdateRefundOrderModel.RefundOrderItemRequest> requestList = refundOrderItemRequestList.stream().filter(r -> r.getLineNum().equals(refundOrderItemRequest.getLineNum())).collect(Collectors.toList());
            if (! CollectionUtils.isEmpty(requestList)){
                UpdateRefundOrderModel.RefundOrderItemRequest orderItemRequest = requestList.get(0);
                refundOrderItemRequest.setNote(orderItemRequest.getNote());
                refundOrderItemRequest.setTotalAmount(orderItemRequest.getTotalAmount());
                refundOrderItemRequest.setUnitPrice(orderItemRequest.getUnitPrice());
            }
        });
        refundOrderModel.setRefundOrderItemRequestInfo(refundOrderItemRequests+"");
        return refundOrderModel;
    }


    public void insertRefundOrderModel(List<CreateRefundOrderModel> createRefundOrderModelList, RefundOrderResult refundOrderResult) {
        RefundOrderResult.ResultData orderResultData = refundOrderResult.getData();
        List<RefundOrderResult.DataModel> errorData = orderResultData.getErrorData();
        List<RefundOrderResult.DataModel> successData = orderResultData.getSuccessData();
        //处理失败的数据
        errorData.forEach(dataModel -> {
            createRefundOrderModelList.stream().filter(createRefundOrderModel -> createRefundOrderModel.getSourceOrderNo().equals(dataModel.getSourceOrderNo()))
                    .findFirst()
                    .ifPresent(o -> {
                        RefundOrderModel refundOrderModel = this.createRefundOrderModel(o, PushStatus.CREATE_ERROR.getStatus(),null);
                        refundOrderMapper.insertRefundOrderModel(refundOrderModel);
                    });
        });
        successData.forEach(dataModel -> {
            createRefundOrderModelList.stream().filter(createRefundOrderModel -> createRefundOrderModel.getSourceOrderNo().equals(dataModel.getSourceOrderNo()))
                    .findFirst()
                    .ifPresent(o -> {
                        RefundOrderModel refundOrderModel = this.createRefundOrderModel(o, PushStatus.CREATE_SUCCESS.getStatus(),dataModel);
                        refundOrderMapper.insertRefundOrderModel(refundOrderModel);
                    });
        });

    }

    private RefundOrderModel createRefundOrderModel(CreateRefundOrderModel o, Integer pushStatus,RefundOrderResult.DataModel dataModel) {
        RefundOrderModel refundOrderModel = new RefundOrderModel();
        BeanUtils.copyProperties(refundOrderModel,o);
        log.info("copy的refundOrderModel数据为{}",JSONObject.toJSONString(refundOrderModel));
        ExtModel extModel = new ExtModel(o.getExt1(),o.getExt2(),o.getExt3(),o.getExt4(),o.getExt5(),o.getExt6(),o.getExt7(),o.getExt8(),o.getExt9(),o.getExt10());
        refundOrderModel.setExt(extractFieldsAsList(extModel) + "");

        List<CreateRefundOrderModel.RefundOrderItemRequest> refundOrderItemRequestList = o.getRefundOrderItemRequestList();
        List<String> lineNumList = dataModel.getLineNumList();
        for (int i = 0; i < refundOrderItemRequestList.size(); i++) {
            refundOrderItemRequestList.get(i).setLineNum(lineNumList.get(i));
        }
        refundOrderModel.setRefundOrderItemRequestInfo(o.getRefundOrderItemRequestList() + "");


        refundOrderModel.setPushStatus(pushStatus);
        refundOrderModel.setSalesOrderNo(dataModel.getSalesOrderNo());
        refundOrderModel.setId(new IdGeneratorSnowflake().snowflakeId());
        refundOrderModel.setCreateTime(new Date());
        return refundOrderModel;
    }

    public List<String> extractFieldsAsList(ExtModel extModel) {
        List<String> fieldValues = new ArrayList<>();
        Field[] fields = extModel.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object value = field.get(extModel);
                if (value != null) {
                    fieldValues.add(value.toString());
                } else {
                    fieldValues.add(null); // or you can add an empty string ""
                }
            } catch (IllegalAccessException e) {
                log.error("extractFieldsAsList异常",e);
            }
        }
        return fieldValues;
    }
}
